import Vue from 'vue'
import VueRouter from 'vue-router'
import store from '@/store'

// 以下代码需要写在路由注册之前
// 目的:解决vue路由跳转错误：Error: Redirected when going from "/login" to "/home" via a navigation guard.
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push (location, onResolve, onReject) {
  if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
  return originalPush.call(this, location).catch(err => err)
}

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    // 一级路由和二级路由都是写的<router-view>,解析器如何正确定位组件放置位置,就是根据这里的
    // component组件+children里定义的路径和组件 简单理解:children里面定义的组件,是放在最外层定义的组件里的<router-view>
    component: () => import('@/views/layout'),
    redirect: '/home', // 重定向会导致路由规则数组再次匹配
    children: [
      {
        path: 'home', // 这里的路由路径需要和后台返回的导航标签路径一致
        component: () => import('@/views/home')
      },
      {
        path: 'user-info', // 这里的路由路径需要和后台返回的导航标签路径一致
        component: () => import('@/views/user/userInfo.vue')
      },
      {
        path: 'user-avatar', // 这里的路由路径需要和后台返回的导航标签路径一致
        component: () => import('@/views/user/userAvatar.vue')
      },
      {
        path: 'user-pwd', // 这里的路由路径需要和后台返回的导航标签路径一致
        component: () => import('@/views/user/userPwd.vue')
      },
      {
        path: 'art-cate', // 这里的路由路径需要和后台返回的导航标签路径一致
        component: () => import('@/views/article/articleCate.vue')
      },
      {
        path: 'art-list', // 这里的路由路径需要和后台返回的导航标签路径一致
        component: () => import('@/views/article/articleList.vue')
      }
    ]
  },
  {
    path: '/reg',
    component: () => import('@/views/register') // 路由懒加载方式，webpack提供，只有切换到该组件时才会加载，提高首页加载速度
  },
  {
    path: '/login',
    component: () => import('@/views/login')
  }
]

const router = new VueRouter({
  routes
})

const whiteList = ['/login', '/reg'] // 无需登录就可以访问的路由地址,前置路由白名单,避免递归出现

// 全局前置路由守卫(浏览器首次打开项目页面也会走,to和from都是自己)
router.beforeEach((to, from, next) => {
  const token = store.state.token
  // 有token就是登录了,没有就是没登录
  if (token) {
    // 每次路由切换都会走前置路由守卫,但是请求不需要这样,只需要本地有token值且vuex的username没有数据时才走请求
    // !store.state.userInfo.username是防止vuex中已经有数据,此时就不重复走请求了
    if (!store.state.userInfo.username) {
      // 调用vuex中actions封装好的方法,将用户信息存储到vuex中(方式二,前置路由守卫)  路由跳转时更新用户信息
      store.dispatch('getUserInfoActions')
    }
    next()
  } else {
    // // 未登录(强制跳转到登录页)
    // next('/login') // 该强制跳转仍然会走前置路由守卫,会出现递归溢出堆栈 解决方法:配置白名单

    // 数组.includes(值)的作用:判断值是否在数组里出现过,出现则原地返回true
    if (whiteList.includes(to.path)) {
      // 通过,在白名单里,是未登录就可以访问的地址,放行
      // 此时路由的全局前置守卫不会再触发,而是匹配路由表,让组件挂载避免递归问题
      next()
    } else {
      // 未登录(不在白名单里)还要去其他页面,则强制跳转登录页
      next('/login') // 去的登录页后就在白名单里面里,再次走前置路由守卫时到不了这里,不会出现递归现象
    }
  }
})

export default router
